package com.yootk.rockemq.util;

import org.apache.rocketmq.common.message.Message;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

// 每次拆分的时候会将完整的消息集合分为子集合的形式出现，每个子集合单独限制其大小
public class MessageListSplitter implements Iterator<List<Message>> {
    private static final int SIZE_LIMIT = 1024 * 1024 * 4; // 固定的数据量
    private List<Message> messages; // 定义集合列表
    // 整个的处理过程之中是需要进行集合长度计算的，这个计算是依据当前迭代的结果完成的\
    private int currentIndex; // 当前处理到的索引
    public MessageListSplitter(List<Message> messages) {
        this.messages = messages; // 集合数据的存储
    }
    @Override
    public boolean hasNext() {
        return this.currentIndex < this.messages.size(); // 后面还有数据
    }

    @Override
    public List<Message> next() { // 获取每一次的部分集合数据
        int startIndex = this.getBeginIndex(); // 获取开始的索引
        int nextIndex = startIndex; // 保存下一个索引
        int totalSize = 0; // 要发送数据的总长度
        for (; nextIndex < this.messages.size(); nextIndex ++) {    // 循环获取集合数据
            Message message = this.messages.get(nextIndex); // 获取当前的数据
            int messageSize = this.calcMessageSize(message); // 计算数据长度
            if (messageSize + totalSize > SIZE_LIMIT) { // 分段
                break;
            } else {
                totalSize += messageSize; // 保存的总长度
            }
        }
        List<Message> subMessages = this.messages.subList(startIndex, nextIndex); // 截取子集合
        this.currentIndex = nextIndex; // 当前的索引
        return subMessages;
    }
    // 如果此时发送的消息量过大了，超过了整个的长度的定义，则进行消息的丢弃
    public int getBeginIndex() {    // 消息处理的时候需要配置一个截取索引
        Message currentMessage = this.messages.get(this.currentIndex); // 获取当前的消息内容
        int messageSize = this.calcMessageSize(currentMessage); // 计算长度
        while (messageSize > SIZE_LIMIT) {  // 保存的长度太大了（超大消息）
            this.currentIndex += 1; // 考虑下一个开始的索引
            Message message = this.messages.get(this.currentIndex);
            messageSize = calcMessageSize(message);
        }
        return this.currentIndex; // 返回索引数据
    }
    public int calcMessageSize(Message message) {   // 计算每个消息的长度
        int tempSize = message.getTopic().length() + message.getBody().length; // 消息的长度
        Map<String, String> properties = message.getProperties(); // 附加属性的处理
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            tempSize += entry.getKey().length() + entry.getValue().length(); // 属性的长度计算
        }
        tempSize = tempSize + 20; // 一些元数据或者是日志信息
        return tempSize; // 返回单个消息的长度
    }
}
